<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Channel 管理 - Netty See</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
    <style>
        .status-active { color: #28a745; }
        .status-inactive { color: #dc3545; }
        .status-closed { color: #6c757d; }
        .channel-card {
            transition: all 0.3s ease;
        }
        .channel-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        .border-left-primary {
            border-left: 4px solid #007bff !important;
        }
        .application-badge {
            font-size: 0.8em;
            font-weight: 500;
        }
        code {
            font-size: 0.85em;
            color: #e83e8c;
            background-color: #f8f9fa;
            padding: 2px 4px;
            border-radius: 3px;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">
                <i class="fas fa-network-wired"></i> Netty See
            </a>
            <div class="navbar-nav ms-auto">
                <a class="nav-link active" href="/channels">Channels</a>
                <a class="nav-link" href="/eventloops">Event Loops</a>
                <a class="nav-link" href="/performance">Performance</a>
                <a class="nav-link" href="/errors">错误分析</a>
            </div>
        </div>
    </nav>

    <div class="container mt-4">
        <div class="row">
            <div class="col-12">
                <div class="d-flex justify-content-between align-items-center mb-4">
                    <h1><i class="fas fa-plug"></i> Channel 管理</h1>
                    <button class="btn btn-primary" onclick="refreshChannels()">
                        <i class="fas fa-sync-alt"></i> 刷新
                    </button>
                </div>
            </div>
        </div>

        <!-- 应用统计概览 -->
        <div class="row mb-4" id="applicationStats">
            <!-- 统计卡片将在这里动态生成 -->
        </div>

        <!-- 过滤条件提示 -->
        <div class="row mb-2" id="filterAlert" style="display: none;">
            <div class="col-12">
                <div class="alert alert-info alert-dismissible fade show" role="alert">
                    <i class="fas fa-filter"></i> <span id="filterMessage"></span>
                    <button type="button" class="btn-close" onclick="clearFilters()"></button>
                </div>
            </div>
        </div>

        <!-- 过滤器 -->
        <div class="row mb-4">
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-text"><i class="fas fa-search"></i></span>
                    <input type="text" class="form-control" id="searchInput" placeholder="搜索 Channel ID 或地址...">
                </div>
            </div>
            <div class="col-md-4">
                <select class="form-select" id="statusFilter">
                    <option value="">所有状态</option>
                    <option value="ACTIVE">活跃</option>
                    <option value="INACTIVE">非活跃</option>
                    <option value="CLOSED">已关闭</option>
                </select>
            </div>
            <div class="col-md-4">
                <select class="form-select" id="applicationFilter">
                    <option value="">所有应用</option>
                </select>
            </div>
        </div>

        <!-- Channel 列表 -->
        <div class="row" id="channelContainer">
            <div class="col-12 text-center">
                <div class="spinner-border" role="status">
                    <span class="visually-hidden">加载中...</span>
                </div>
            </div>
        </div>
    </div>

    <!-- Channel 详情模态框 -->
    <div class="modal fade" id="channelDetailModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Channel 详情</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body" id="channelDetailContent">
                    <!-- 详情内容将在这里动态加载 -->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    <button type="button" class="btn btn-danger" onclick="closeChannel()">关闭连接</button>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        let channels = [];
        let currentChannelId = null;

        function refreshChannels() {
            // 显示加载状态
            document.getElementById('channelContainer').innerHTML = `
                <div class="col-12 text-center">
                    <div class="spinner-border" role="status">
                        <span class="visually-hidden">加载中...</span>
                    </div>
                    <div class="mt-2">正在刷新Channel数据...</div>
                </div>
            `;
            
            fetch('/api/netty/channels')
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
                    }
                    return response.json();
                })
                .then(data => {
                    channels = Array.isArray(data) ? data : [];
                    updateApplicationFilter();
                    renderChannels(channels);
                    console.log('Channel数据刷新成功，共', channels.length, '个Channel');
                })
                .catch(error => {
                    console.error('获取Channel数据失败:', error);
                    document.getElementById('channelContainer').innerHTML = `
                        <div class="col-12">
                            <div class="alert alert-danger">
                                <i class="fas fa-exclamation-triangle"></i>
                                获取Channel数据失败: ${error.message}
                                <br><small>请检查服务器是否正常运行，或尝试重新刷新页面</small>
                            </div>
                        </div>
                    `;
                });
        }

        function updateApplicationFilter() {
            const applications = [...new Set(channels.map(ch => ch.applicationName).filter(app => app))];
            const select = document.getElementById('applicationFilter');
            
            // 保存当前选择
            const currentValue = select.value;
            
            // 清空并重新填充选项
            select.innerHTML = '<option value="">所有应用</option>';
            applications.forEach(app => {
                const option = document.createElement('option');
                option.value = app;
                option.textContent = app;
                select.appendChild(option);
            });
            
            // 恢复选择
            select.value = currentValue;
            
            // 更新应用统计
            updateApplicationStats();
        }

        function updateApplicationStats() {
            const appStats = {};
            
            channels.forEach(channel => {
                const app = channel.applicationName || 'Unknown';
                if (!appStats[app]) {
                    appStats[app] = { total: 0, active: 0, inactive: 0, closed: 0 };
                }
                appStats[app].total++;
                
                switch(channel.state) {
                    case 'ACTIVE':
                        appStats[app].active++;
                        break;
                    case 'INACTIVE':
                        appStats[app].inactive++;
                        break;
                    case 'CLOSED':
                        appStats[app].closed++;
                        break;
                }
            });
            
            const statsContainer = document.getElementById('applicationStats');
            const statsHtml = Object.entries(appStats).map(([app, stats]) => `
                <div class="col-md-3 mb-3">
                    <div class="card border-left-primary">
                        <div class="card-body">
                            <div class="d-flex justify-content-between align-items-center">
                                <div>
                                    <h6 class="card-title mb-1">
                                        <i class="fas fa-desktop text-primary"></i> ${app}
                                    </h6>
                                    <div class="text-muted small">
                                        总计: ${stats.total} | 
                                        <span class="text-success">活跃: ${stats.active}</span> | 
                                        <span class="text-warning">非活跃: ${stats.inactive}</span> | 
                                        <span class="text-secondary">关闭: ${stats.closed}</span>
                                    </div>
                                </div>
                                <div class="text-right">
                                    <button class="btn btn-sm btn-outline-primary" onclick="filterByApplication('${app}')">
                                        <i class="fas fa-filter"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            `).join('');
            
            statsContainer.innerHTML = statsHtml;
        }

        function filterByApplication(appName) {
            document.getElementById('applicationFilter').value = appName;
            filterChannels();
        }

        function renderChannels(channelList) {
            const container = document.getElementById('channelContainer');
            
            if (channelList.length === 0) {
                container.innerHTML = '<div class="col-12"><div class="alert alert-info">暂无Channel数据</div></div>';
                return;
            }

            const html = channelList.map(channel => `
                <div class="col-md-6 col-lg-4 mb-3">
                    <div class="card channel-card h-100">
                        <div class="card-header d-flex justify-content-between align-items-center">
                            <small class="text-muted">${channel.channelId}</small>
                            <span class="badge ${getStatusBadgeClass(channel.state)}">${channel.state}</span>
                        </div>
                        <div class="card-body">
                            <h6 class="card-title">
                                <i class="fas fa-${channel.active ? 'plug' : 'plug-circle-xmark'}"></i>
                                ${channel.active ? '活跃连接' : '非活跃连接'}
                            </h6>
                            <div class="mb-2">
                                <span class="badge bg-info text-dark">
                                    <i class="fas fa-desktop"></i> ${channel.applicationName || 'Unknown'}
                                </span>
                            </div>
                            <p class="card-text">
                                <small class="text-muted">远程地址:</small><br>
                                <code>${channel.remoteAddress}</code><br>
                                <small class="text-muted">本地地址:</small><br>
                                <code>${channel.localAddress}</code>
                            </p>
                            <div class="d-flex justify-content-between">
                                <small class="text-muted">创建: ${formatTime(channel.createTime)}</small>
                            </div>
                        </div>
                        <div class="card-footer">
                            <button class="btn btn-sm btn-outline-primary" onclick="showChannelDetail('${channel.channelId}')">
                                <i class="fas fa-info-circle"></i> 详情
                            </button>
                            <button class="btn btn-sm btn-outline-secondary" onclick="showBufferInfo('${channel.channelId}')">
                                <i class="fas fa-memory"></i> 缓冲区
                            </button>
                        </div>
                    </div>
                </div>
            `).join('');

            container.innerHTML = html;
        }

        function getStatusBadgeClass(status) {
            switch(status) {
                case 'ACTIVE': return 'bg-success';
                case 'INACTIVE': return 'bg-warning';
                case 'CLOSED': return 'bg-secondary';
                default: return 'bg-secondary';
            }
        }

        function formatTime(timeString) {
            if (!timeString) return 'N/A';
            return new Date(timeString).toLocaleString();
        }

        function showChannelDetail(channelId) {
            const channel = channels.find(ch => ch.channelId === channelId);
            if (!channel) return;

            currentChannelId = channelId;
            
            const content = `
                <div class="row">
                    <div class="col-md-6">
                        <h6><i class="fas fa-info-circle"></i> 基本信息</h6>
                        <table class="table table-sm">
                            <tr><td><strong>应用名称</strong></td><td><span class="badge bg-info">${channel.applicationName || 'Unknown'}</span></td></tr>
                            <tr><td><strong>Channel ID</strong></td><td><code>${channel.channelId}</code></td></tr>
                            <tr><td><strong>状态</strong></td><td><span class="badge ${getStatusBadgeClass(channel.state)}">${channel.state}</span></td></tr>
                            <tr><td><strong>活跃</strong></td><td>${channel.active ? '<i class="fas fa-check text-success"></i> 是' : '<i class="fas fa-times text-danger"></i> 否'}</td></tr>
                            <tr><td><strong>开放</strong></td><td>${channel.open ? '<i class="fas fa-check text-success"></i> 是' : '<i class="fas fa-times text-danger"></i> 否'}</td></tr>
                            <tr><td><strong>可写</strong></td><td>${channel.writable ? '<i class="fas fa-check text-success"></i> 是' : '<i class="fas fa-times text-danger"></i> 否'}</td></tr>
                        </table>
                    </div>
                    <div class="col-md-6">
                        <h6><i class="fas fa-network-wired"></i> 网络信息</h6>
                        <table class="table table-sm">
                            <tr><td><strong>远程地址</strong></td><td><code>${channel.remoteAddress}</code></td></tr>
                            <tr><td><strong>本地地址</strong></td><td><code>${channel.localAddress}</code></td></tr>
                            <tr><td><strong>EventLoop</strong></td><td><span class="badge bg-secondary">${channel.eventLoopGroup || 'N/A'}</span></td></tr>
                        </table>
                    </div>
                </div>
                <div class="row">
                    <div class="col-md-6">
                        <h6><i class="fas fa-clock"></i> 时间信息</h6>
                        <table class="table table-sm">
                            <tr><td><strong>创建时间</strong></td><td>${formatTime(channel.createTime)}</td></tr>
                            <tr><td><strong>最后活跃</strong></td><td>${formatTime(channel.lastActiveTime)}</td></tr>
                        </table>
                    </div>
                    <div class="col-md-6">
                        <h6><i class="fas fa-chart-bar"></i> 统计信息</h6>
                        <table class="table table-sm">
                            <tr><td><strong>读取字节</strong></td><td>${channel.bytesRead || 0} bytes</td></tr>
                            <tr><td><strong>写入字节</strong></td><td>${channel.bytesWritten || 0} bytes</td></tr>
                            <tr><td><strong>读取消息</strong></td><td>${channel.messagesRead || 0}</td></tr>
                            <tr><td><strong>写入消息</strong></td><td>${channel.messagesWritten || 0}</td></tr>
                        </table>
                    </div>
                </div>
                <div class="row">
                    <div class="col-12">
                        <h6><i class="fas fa-sitemap"></i> Pipeline 信息</h6>
                        <pre class="bg-light p-2 border rounded"><code>${channel.pipeline || 'N/A'}</code></pre>
                    </div>
                </div>
            `;

            document.getElementById('channelDetailContent').innerHTML = content;
            new bootstrap.Modal(document.getElementById('channelDetailModal')).show();
        }

        function showBufferInfo(channelId) {
            fetch(`/api/netty/channels/${channelId}/buffer`)
                .then(response => response.json())
                .then(data => {
                    if (data) {
                        alert(`缓冲区信息:\n容量: ${data.capacity || 'N/A'}\n可读字节: ${data.readableBytes || 'N/A'}\n可写字节: ${data.writableBytes || 'N/A'}`);
                    } else {
                        alert('无法获取缓冲区信息');
                    }
                })
                .catch(error => {
                    console.error('获取缓冲区信息失败:', error);
                    alert('获取缓冲区信息失败');
                });
        }

        function closeChannel() {
            if (!currentChannelId) return;
            
            if (confirm('确定要关闭这个Channel吗？')) {
                fetch(`/api/netty/channels/${currentChannelId}`, { method: 'DELETE' })
                    .then(() => {
                        bootstrap.Modal.getInstance(document.getElementById('channelDetailModal')).hide();
                        refreshChannels();
                    })
                    .catch(error => {
                        console.error('关闭Channel失败:', error);
                        alert('关闭Channel失败');
                    });
            }
        }

        // 搜索和过滤功能
        function filterChannels() {
            const searchTerm = document.getElementById('searchInput').value.toLowerCase();
            const statusFilter = document.getElementById('statusFilter').value;
            const applicationFilter = document.getElementById('applicationFilter').value;
            const params = getUrlParams();
            
            let filtered = channels.filter(channel => {
                const matchesSearch = !searchTerm || 
                    channel.channelId.toLowerCase().includes(searchTerm) ||
                    channel.remoteAddress.toLowerCase().includes(searchTerm) ||
                    channel.localAddress.toLowerCase().includes(searchTerm) ||
                    (channel.applicationName && channel.applicationName.toLowerCase().includes(searchTerm));
                
                const matchesStatus = !statusFilter || channel.state === statusFilter;
                const matchesApplication = !applicationFilter || channel.applicationName === applicationFilter;
                
                // EventLoop过滤逻辑
                const matchesEventLoop = !params.eventloop || 
                    (channel.eventLoopGroup && channel.eventLoopGroup.toLowerCase().includes(params.eventloop.toLowerCase()));
                
                return matchesSearch && matchesStatus && matchesApplication && matchesEventLoop;
            });
            
            renderChannels(filtered);
        }

        // 事件监听器
        document.getElementById('searchInput').addEventListener('input', filterChannels);
        document.getElementById('statusFilter').addEventListener('change', filterChannels);
        document.getElementById('applicationFilter').addEventListener('change', filterChannels);

        // 从URL参数中获取搜索条件
        function getUrlParams() {
            const urlParams = new URLSearchParams(window.location.search);
            return {
                search: urlParams.get('search'),
                status: urlParams.get('status'),
                application: urlParams.get('application'),
                eventloop: urlParams.get('eventloop')
            };
        }

        // 应用URL参数到过滤器
        function applyUrlParams() {
            const params = getUrlParams();
            
            if (params.search) {
                document.getElementById('searchInput').value = params.search;
            }
            
            if (params.status) {
                document.getElementById('statusFilter').value = params.status;
            }
            
            if (params.application) {
                document.getElementById('applicationFilter').value = params.application;
            }
            
            // 显示过滤条件提示
            showFilterAlert(params);
            
            // 应用过滤
            if (params.search || params.status || params.application || params.eventloop) {
                filterChannels();
            }
        }

        // 显示过滤条件提示
        function showFilterAlert(params) {
            const filterMessages = [];
            
            if (params.search) {
                filterMessages.push(`搜索: "${params.search}"`);
            }
            
            if (params.status) {
                filterMessages.push(`状态: ${params.status}`);
            }
            
            if (params.application) {
                filterMessages.push(`应用: ${params.application}`);
            }
            
            if (params.eventloop) {
                filterMessages.push(`EventLoop: "${params.eventloop}"`);
            }
            
            if (filterMessages.length > 0) {
                document.getElementById('filterMessage').textContent = 
                    `当前过滤条件: ${filterMessages.join(', ')}`;
                document.getElementById('filterAlert').style.display = 'block';
            }
        }

        // 清除所有过滤条件
        function clearFilters() {
            document.getElementById('searchInput').value = '';
            document.getElementById('statusFilter').value = '';
            document.getElementById('applicationFilter').value = '';
            document.getElementById('searchInput').placeholder = '搜索 Channel ID 或地址...';
            document.getElementById('filterAlert').style.display = 'none';
            
            // 清除URL参数
            const url = new URL(window.location);
            url.search = '';
            window.history.replaceState({}, '', url);
            
            // 重新渲染所有channels
            renderChannels(channels);
        }

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            refreshChannels();
            
            // 数据加载完成后应用URL参数
            setTimeout(() => {
                applyUrlParams();
            }, 1000);
            
            setInterval(refreshChannels, 10000); // 每10秒自动刷新
        });
    </script>
</body>
</html>